package com.cat.common.util;

import java.io.UnsupportedEncodingException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class EncryptionUtil {

	private static final Logger logger = LoggerFactory.getLogger(EncryptionUtil.class);
	public static final String src = "rsa test";

	public static String getMD5Digest(String strInfo) {
		String strInfoDigest = "";
		try {
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			messageDigest.update(strInfo.getBytes());
			byte bInfoDigest[] = messageDigest.digest();
			strInfoDigest = byteToHex(bInfoDigest);
		} catch (NoSuchAlgorithmException ex) {
			logger.info("加密失败");
		}
		return strInfoDigest;
	}
	
	
	public static String getMd5Value(String str) {
		if(str==null)
			return "";
		
		try {
			MessageDigest bmd5 = MessageDigest.getInstance("MD5");
			bmd5.update(str.getBytes());
			int i;
			StringBuffer buf = new StringBuffer();
			byte[] b = bmd5.digest();
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			return buf.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return "";

	}

	public static String encode(String content) {
        try {
                MessageDigest digest = MessageDigest.getInstance("MD5");
                digest.update(content.getBytes());
               // return getEncode16(digest);
                return getEncode32(digest);
        } catch (Exception e) {

        }
        return null;
}
	
	private static String getEncode32(MessageDigest digest) {
        StringBuilder builder = new StringBuilder();
        for (byte b : digest.digest()) {
                builder.append(Integer.toHexString((b >> 4) & 0xf));
                builder.append(Integer.toHexString(b & 0xf));
        }
        //return builder.toString().toLowerCase(); // 小写
        //return builder.toString().toUpperCase(); // 大写
        // java.lang.String.toUpperCase(Locale locale) 方法将在此字符串中的所有字符为大写的规则给定的Locale.
        //return builder.toString().toUpperCase(Locale.getDefault()); // 大写
        return builder.toString(); 
}
	
	private static String getEncode16(MessageDigest digest) {
        StringBuilder builder = new StringBuilder();
        for (byte b : digest.digest()) {
                builder.append(Integer.toHexString((b >> 4) & 0xf));
                builder.append(Integer.toHexString(b & 0xf));
        }

        // 16位加密，从第9位到25位  
        //return builder.substring(8, 24).toString().toUpperCase();  
        return builder.substring(8, 24).toString();  
}
	
	public static String byteToHex(byte bInfoDigest[]) {
		String strInfoDigest = "";
		String strTemp = "";
		for (int i = 0; i < bInfoDigest.length; i++) {
			strTemp = Integer.toHexString(bInfoDigest[i] & 0xff);
			if (strTemp.length() == 1)
				strInfoDigest = strInfoDigest + "0" + strTemp;
			else
				strInfoDigest = strInfoDigest + strTemp;
		}
		strInfoDigest = strInfoDigest.toUpperCase();
		return strInfoDigest;
	}
	
	/**
	 * base64 加密
	 * @author ning
	 * @date 2016-1-22
	 */
	public static String str2Base64(String str){
		byte[] b = null;  
        String s = null;  
        try {  
            b = str.getBytes("utf-8");  
        } catch (UnsupportedEncodingException e) {  
            e.printStackTrace();  
        }  
        if (b != null) {  
            s = new BASE64Encoder().encode(b);  
        }  
        return s;
	}
	/**
	 * base64 解密
	 * @author ning
	 * @date 2016-1-22
	 */
	public static String Base642Str(String s){
		byte[] b = null;  
        String result = null;  
        if (s != null) {  
            BASE64Decoder decoder = new BASE64Decoder();  
            try {  
                b = decoder.decodeBuffer(s);  
                result = new String(b, "utf-8");  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
        return result;  
	}
	
	
	/**
	 * 加密
	 * @param    
	 * @return void  
	 * @throws
	 * @author ning
	 * @date 2016-1-4
	 */
	public void jdkRSA()
	{		
		try 
		{
			// 1.初始化发送方密钥
			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
			keyPairGenerator.initialize(512);
			KeyPair keyPair = keyPairGenerator.generateKeyPair();
			RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
			RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
			System.out.println("Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
			System.out.println("Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
			
			// 2.私钥加密、公钥解密 ---- 加密
			PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.ENCRYPT_MODE, privateKey);
			byte[] result = cipher.doFinal(src.getBytes());
			System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));
			
			// 3.私钥加密、公钥解密 ---- 解密
			X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
			keyFactory = KeyFactory.getInstance("RSA");
			PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
			cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, publicKey);
			result = cipher.doFinal(result);
			System.out.println("私钥加密、公钥解密 ---- 解密:" + new String(result));
			
			
			
			// 4.公钥加密、私钥解密 ---- 加密
			X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
			KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");
			PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
			Cipher cipher2 = Cipher.getInstance("RSA");
			cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
			byte[] result2 = cipher2.doFinal(src.getBytes());
			System.out.println("公钥加密、私钥解密 ---- 加密:" + Base64.encodeBase64String(result2));
			
			// 5.私钥解密、公钥加密 ---- 解密
			PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
			KeyFactory keyFactory5 = KeyFactory.getInstance("RSA");
			PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
			Cipher cipher5 = Cipher.getInstance("RSA");
			cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
			byte[] result5 = cipher5.doFinal(result2);
			System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result5));
			
		} catch (Exception e) {
			
			e.printStackTrace();
		}
		
	}
	
	
	/**
	* 加密
	* @param datasource byte[]
	* @param password String
	* @return string
	*/
	public static String DesEncrypt(String datasource, String password) { 
		try{
			SecureRandom random = new SecureRandom();
			DESKeySpec desKey = new DESKeySpec(password.getBytes());
			//创建一个密匙工厂，然后用它把DESKeySpec转换成
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey securekey = keyFactory.generateSecret(desKey);
			//Cipher对象实际完成加密操作
			Cipher cipher = Cipher.getInstance("DES");
			//用密匙初始化Cipher对象
			cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
			//现在，获取数据并加密
			//正式执行加密操作
			return byteArr2HexStr(cipher.doFinal(datasource.getBytes()));
		}catch(Throwable e){
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	* 解密
	* @param src byte[]
	* @param password String
	* @return String
	* @throws Exception
	*/
	public static String DesDecrypt(String src, String password) {
		try {
			// DES算法要求有一个可信任的随机数源
			SecureRandom random = new SecureRandom();
			// 创建一个DESKeySpec对象
			DESKeySpec desKey = new DESKeySpec(password.getBytes());
			// 创建一个密匙工厂
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			// 将DESKeySpec对象转换成SecretKey对象
			SecretKey securekey = keyFactory.generateSecret(desKey);
			// Cipher对象实际完成解密操作
			Cipher cipher = Cipher.getInstance("DES");
			// 用密匙初始化Cipher对象
			cipher.init(Cipher.DECRYPT_MODE, securekey, random);
			// 真正开始解密操作
			return new String(cipher.doFinal(hexStr2ByteArr(src)));
		}catch(Throwable e){
			e.printStackTrace();
		}
		return null;
	}
	
	 /** 
     * 将byte数组转换为表示16进制值的字符串， 
     * 如：byte[]{8,18}转换为：0813， 
     * 和public static byte[] hexStr2ByteArr(String strIn) 
     * 互为可逆的转换过程 
     * @param arrB 需要转换的byte数组 
     * @return 转换后的字符串 
     * @throws Exception 本方法不处理任何异常，所有异常全部抛出 
     */  
	 public static String byteArr2HexStr(byte[] arrB) throws Exception {  
        int iLen = arrB.length;  
        StringBuffer sb = new StringBuffer(iLen * 2);  
        for (int i = 0; i < iLen; i++) {  
            int intTmp = arrB[i];  
            while (intTmp < 0) {  
                intTmp = intTmp + 256;  
            }  
            if (intTmp < 16) {  
                sb.append("0");  
            }  
            sb.append(Integer.toString(intTmp, 16));  
        }  
        return sb.toString();  
    } 
	
	 /** 
     * 将表示16进制值的字符串转换为byte数组， 
     * 和public static String byteArr2HexStr(byte[] arrB) 
     * 互为可逆的转换过程 
     * @param strIn 需要转换的字符串 
     * @return 转换后的byte数组 
     * @throws Exception 本方法不处理任何异常，所有异常全部抛出 
     */  
    public static byte[] hexStr2ByteArr(String strIn) throws Exception {  
        byte[] arrB = strIn.getBytes();  
        int iLen = arrB.length;  
        byte[] arrOut = new byte[iLen / 2];  
        for (int i = 0; i < iLen; i = i + 2) {  
            String strTmp = new String(arrB, i, 2);  
            arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);  
        }  
        return arrOut;  
    }  
	  
	
	public static void main(String[] args) {
		System.out.println(EncryptionUtil.getMD5Digest("1234"));
	}
	

}
